package cn.virens;

import cn.virens.app.AppConfig;
import cn.virens.app.ApplicationLoader;
import cn.virens.app.cmpt.ComponentRegistry;
import cn.virens.app.timer.TimedTaskRegistry;
import cn.virens.cmpt.database.DatabaseManager;
import cn.virens.cmpt.database.DatabaseManagerImpl;
import cn.virens.cmpt.rabbit.RabbitManager;
import cn.virens.cmpt.rabbit.RabbitManagerImpl;
import cn.virens.cmpt.trayicon.TrayIconComponent;
import cn.virens.server.aio.AioServerManage;
import cn.virens.server.aio.AioServerManageImpl;
import cn.virens.server.aio.AioServerMonitor;
import cn.virens.server.aio.handler.PacketHandlerSimple;
import cn.virens.server.aio.listener.simple.SimpleAioDataDecoder;
import cn.virens.server.aio.listener.simple.SimpleAioDataEncoder;
import cn.virens.server.aio.listener.simple.SimpleAioDataErrorListener;
import cn.virens.server.aio.listener.simple.SimpleAioDataReadListener;
import cn.virens.server.aio.listener.simple.SimpleAioDataWriteListener;
import cn.virens.server.aio.listener.simple.SimpleAioStateCloseableListener;
import cn.virens.server.aio.listener.simple.SimpleAioStateConnectedListener;
import cn.virens.server.aio.listener.simple.SimpleAioStateExceptionListener;
import cn.virens.server.aio.packet.AioWritePacket;
import cn.virens.server.netty_tcp.TCPServerManagerImpl;
import cn.virens.server.netty_udp.UDPServerManagerImpl;
import cn.virens.server.tio_http.WebServerManagerImpl;
import cn.virens.server.tio_tcp.TIOServerManagerImpl;

@SuppressWarnings("unused")
public class App extends ApplicationLoader {
	private final static App app = new App();

	private RabbitManagerImpl mRabbitManager = null;
	private DatabaseManagerImpl mDatabaseManager = null;
	private AioServerManageImpl mAioServerManageImpl = null;
	private WebServerManagerImpl mWebServerManagerImpl = null;
	private TIOServerManagerImpl mTIOServerManagerImpl = null;
	private TCPServerManagerImpl mTCPServerManagerImpl = null;
	private UDPServerManagerImpl mUDPServerManagerImpl = null;

	private TrayIconComponent mTrayIcon = null;

	public static void main(String[] args) throws Exception {
		load(app, args);
	}

	@Override
	protected void startComponent(ComponentRegistry regcmpt, String[] args) {
		this.mTrayIcon = regcmpt.register(new TrayIconComponent());
		this.mRabbitManager = regcmpt.register(new RabbitManagerImpl()); // 消息队列组件
		this.mDatabaseManager = regcmpt.register(new DatabaseManagerImpl()); // 数据库组件
		this.mAioServerManageImpl = regcmpt.register(new AioServerManageImpl());// AIO Server组件
		//		this.mTIOServerManagerImpl = regcmpt.register(new TIOServerManagerImpl());// TIO TCP Server组件
		//		this.mWebServerManagerImpl = regcmpt.register(new WebServerManagerImpl());// TIO WEB Server组件
		//		this.mTCPServerManagerImpl = regcmpt.register(new TCPServerManagerImpl());// Netty TCP Server组件
		//		this.mUDPServerManagerImpl = regcmpt.register(new UDPServerManagerImpl());// Netty UDP Server组件
	}

	@Override
	protected void startTimedTask(TimedTaskRegistry regtimer, String[] args) {
		regtimer.register(new AioServerMonitor());
	}

	@Override
	protected void stopComponent(ComponentRegistry regcmpt) {

	}

	@Override
	protected void stopTimedTask(TimedTaskRegistry regtimer) {

	}

	@Override
	public void initialize(AppConfig config) throws Exception {
		this.mAioServerManageImpl.setAioDataDecoder(new SimpleAioDataDecoder());
		this.mAioServerManageImpl.setAioDataEncoder(new SimpleAioDataEncoder());
		this.mAioServerManageImpl.setAioDataReadListener(new SimpleAioDataReadListener());
		this.mAioServerManageImpl.setAioDataWriteListener(new SimpleAioDataWriteListener());
		this.mAioServerManageImpl.setAioDataErrorListener(new SimpleAioDataErrorListener());
		this.mAioServerManageImpl.setAioStateCloseableListener(new SimpleAioStateCloseableListener());
		this.mAioServerManageImpl.setAioStateConnectedListener(new SimpleAioStateConnectedListener());
		this.mAioServerManageImpl.setAioStateExceptionListener(new SimpleAioStateExceptionListener());

		this.mAioServerManageImpl.addHandler(PacketHandlerSimple.of(-1, (channel, packet) -> {
			mAioServerManageImpl.send(channel, AioWritePacket.of(packet));
		}));
	}

	@Override
	public void destroy() throws Exception {
	}

	/**
	 * 退出应用
	 */
	public void exit() {
		ApplicationLoader.unload(app, null);
	}

	public synchronized static App app() {
		return app;
	}

	/** AIO服务组件 */
	public static AioServerManage aio() {
		return app().mAioServerManageImpl;
	}

	/** 数据库组件 */
	public static DatabaseManager db() {
		return app().mDatabaseManager;
	}

	/** 消息队列组件 */
	public static RabbitManager mq() {
		return app().mRabbitManager;
	}
}
